# remote operations module
# (c) 2008-2009 NIXON Development Corporation.

import wx
import time, locale, format
import wx.lib.delayedresult as delayedResult
from ftplib import error_temp, error_perm, error_proto

class dirListing():
	def __init__(self, prnt):
		self.lnames = []
		self.ResetDictionaries()
		self.len = 0
		self.prnt = prnt
		locale.setlocale(locale.LC_ALL, '')

	def doPath(self, path, hoc, pasv=False):
		if pasv:
			if self.indexed(path): return
			
		self.lnames = []
		self.curpath = path
		if path == '': cd = '/'
		else: cd = path
		
		if not(hoc.chgDir(cd)):
			tmr = time.clock()
			hoc.hftp.retrlines('LIST -a', self.retDirUNIX)
			s = time.clock() - tmr
			print(self.getSpeed(self.len * 8, s))
			self.len = 0
			
			self.dnames[path] = self.lnames
			return path
		else:
			return -1

	def getSpeed(self, bits, secs):
		speed = bits / secs

		tpUnits = ('','K','M','G','T')
		for x in range(1, 6):
			if speed < (1000 ** x) or x == 5:
				speed = float(bits) / float(1000 ** (x-1)) / float(secs)
				units = tpUnits[x-1] + 'bps'
				break

		str = locale.format('%.2f ' + units, speed, True)
		return 'Received %d bytes in %.3g seconds (' % (bits / 8, secs) + str + ')'

	def retDir(self, str): # Windows_NT
		date = (str[0:17])
		date = time.strptime(date, '%m-%d-%y %I:%M%p')
		str = str[17:len(str)].strip(' ')
		result2 = str.find(' ')
		str2 = str[0:result2]
		if str2 == '<DIR>':
			perms = 'd'
			size = '-1'
		else:
			perms = '-'
			size = str2

		str = str[result2:len(str)].strip(' ')

		lst = (perms, 0, 'Unknown', 'Unknown', size, date, str)
		self.dfiles[self.curpath + '/' + str] = lst
		self.lnames.append(str)

	def retDirUNIX(self, str):	
		strTest = str[:1]
		#if strTest != 'd' and strTest != 'l' and strTest != '-' and strTest != 't':
		try:
			intTest = int(strTest)
			self.retDir(str)
		except:
			if str[0:5] != 'total':
				perms = str[0:10]
				st = str[11:len(str)].strip(' ') #Hard Links

				lstVar = []

				for x in range(0, 4): #Hard links, Owner, Group, Size
					result2 = st.find(' ')
					lstVar.append(st[0:result2])
					if x != 3:
						st = st[result2:len(st)].strip(' ')

				sDate = st[result2+1:result2+13]

				if sDate.find(':') == -1:
					stDate = time.strptime(sDate, '%b %d %Y')
				else:
					sd = sDate[0:6]
					stime = sDate[6:12]
					sy = time.strftime('%Y', time.localtime())
					sDate = sd + " " + sy + " " + stime
					stDate = time.strptime(sDate, '%b %d %Y %H:%M')

				sName = st[result2+14:len(st)]

				if sName != '.' and sName != '..':
					lst = (perms, lstVar[0], lstVar[1], lstVar[2], lstVar[3], stDate, sName)
					
					if str[:1] == 'd' or str[:1] == '-':
						self.dfiles[self.curpath + '/' + sName] = lst
						self.lnames.append(sName)
					elif str[:1] == 'l':
						f = sName.find(' -> ')
						hl = sName[0:f]
						self.dfiles[self.curpath + '/' + hl] = lst
						self.lnames.append(hl)

		self.len += len(str)
		self.prnt.pnRemote.statusText.SetLabel('Received ' + format.parseSize(self.len))
					
	def indexed(self, pwf):
		try:
			tst = self.dnames[pwf]
			return True
		except: return False

	def getInfo(self, pwf):
		return self.dfiles[pwf]
				
	def getType(self, pwf):
		info = self.getInfo(pwf)[0][:1]
		if info == 'l':
			return 1
		elif info == 'd':
			return 2
		elif info == '-':
			return 0

	def getNames(self, path):
		try:
			return self.dnames[path]
		except: return

	def getPerms(self, pwf):
		try:
			return self.dfiles[pwf][0]
		except: return

	def getSizes(self, pwf):
		try:
			return self.dfiles[pwf][4]
		except: return

	def getReals(self,pwf):
		try:
			return self.dfiles[pwf][6]
		except: return

	def getGroups(self, pwf):
		try:
			return self.dfiles[pwf][3]
		except: return

	def getOwners(self, pwf):
		try:
			return self.dfiles[pwf][2]
		except: return

	def getDates(self, pwf):
		try:
			return self.dfiles[pwf][5]
		except: return
		
	def getDest(self, pwf):
		sel = self.getReals(pwf)
		pos = sel.find(' -> ')
		return sel[pos + 4:]

	def ResetDictionaries(self):
		self.dfiles = {}
		self.dnames = {}

class taskList():
	intId = 99
	
	class taskTimer(wx.Timer):
		def __init__(self, prnt):
			wx.Timer.__init__(self)
			self.prnt = prnt
			self.needsUpdate = False
			prnt.intSecs = 0
			
		def Notify(self):
			self.prnt.intSecs += 1
			self.needsUpdate = True
		
	def getNewId(self):
		self.intId += 1
		return self.intId
	
	def __init__(self, frame):
		self.operList = []
		self.failList = []
		self.frame = frame
		self.timer = self.taskTimer(self)
		
	def addTask(self, func, argv, callback=None, urgent=False):		
		newTask = task(func, argv, self.getNewId(), callback)
		if urgent:
			self.operList.insert(0, newTask)
		else:
			self.operList.append(newTask)

		if len(self.operList) == 1:
			self.doQueue()
			
	def consumer(self, delayedresult):
		if len(self.operList) > 0:
			t = self.operList.pop(0)
				
			if t.callback: t.callback(delayedresult)
			self.timer.Stop()
			self.intSecs = 0

		self.processQueue()
		
	def processQueue(self):
		if len(self.operList) == 0:
			self.frame.mFTP.keepAlive.Start()
			self.frame.doQueue(False)
		else:
			self.doQueue()

	def doQueue(self):
		hTask = self.operList[0]
		try:
			self.timer.Start(500)
			self.frame.mFTP.keepAlive.Stop()
			delayedResult.startWorker(self.consumer, hTask.func, wargs=hTask.argv)
		except: self.processQueue()
			
	def getString(self, int):
		if int == 0:
			file = 'downloading'
		elif int == 1:
			file = 'uploading'
		else:
			file = 'go'
			
		return file
		
	def addFail(self):
		failTask = self.operList[0]
		self.failList.append(failTask)
		#self.getFailed()
		
	def getFailed(self):
		for x in self.failList:
			print repr(x.func) + '(' + repr(x.args) + ')'
			
class task():
	def __init__(self, func, argv, id, callback):
		self.func = func
		self.argv = argv
		self.id = id
		self.callback = callback